package com.ibeeking.found.id.rest.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibeeking.found.common.enums.NoRuleEnum;
import com.ibeeking.found.common.enums.SerialNumberTypeEnum;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.id.api.common.dto.*;
import com.ibeeking.found.id.rest.redis.RedisIdTemplate;
import com.ibeeking.found.id.rest.redis.SimpleDateFormatter;
import com.ibeeking.found.id.rest.service.ISerialNoRuleGenerateService;
import com.ibeeking.found.id.rest.service.SerialNumberService;
import com.ibeeking.found.id.service.common.dos.SerialNoRuleDO;
import com.ibeeking.found.id.service.common.param.*;
import com.ibeeking.found.id.service.mapper.SerialNoRuleMapper;
import com.ibeeking.nematos.constants.enums.LogClassifyEnum;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.alibaba.nacos.shaded.com.google.protobuf.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;


import javax.annotation.Resource;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SerialNoRuleGenerateServiceImpl extends ServiceImpl<SerialNoRuleMapper, SerialNoRuleDO> implements ISerialNoRuleGenerateService {

    @Resource
    private SerialNoRuleMapper serialNoRuleMapper;

    @Resource
    private RedisIdTemplate redisIdTemplate;

    @Resource
    private SerialNumberService serialNumberService;

    @Override
    public Boolean add(SerialNoRuleParam serialNoRuleParam) {
        SerialNoRuleDO serialNoRuleDO = BeanUtil.convertBean(serialNoRuleParam, SerialNoRuleDO.class);
        serialNoRuleDO.setCreateTime(LocalDateTime.now());
        serialNoRuleDO.setModifyTime(LocalDateTime.now());
        return serialNoRuleMapper.insert(serialNoRuleDO) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchAdd(List<SerialNoRuleParam> serialNoRuleParams) {
        if (Collections3.isEmpty(serialNoRuleParams)) {
            return false;
        }
        List<SerialNoRuleDO> serialNoRuleDOS = JsonUtils.jsonToList(serialNoRuleParams, SerialNoRuleDO.class);
        serialNoRuleDOS.stream().forEach(d->{
            d.setCreateTime(LocalDateTime.now());
            d.setModifyTime(LocalDateTime.now());
        });
        return serialNoRuleMapper.insertBatchSomeColumn(serialNoRuleDOS) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchModify(List<SerialNoRuleParam> serialNoRuleParams) {
        if (Collections3.isEmpty(serialNoRuleParams)) {
            return false;
        }
        List<SerialNoRuleDO> serialNoRuleDOS = JsonUtils.jsonToList(serialNoRuleParams, SerialNoRuleDO.class);
        serialNoRuleDOS.stream().forEach(d->{
            d.setModifyTime(LocalDateTime.now());
        });
        return this.updateBatchById(serialNoRuleDOS);
    }

    @Override
    public Boolean modify(SerialNoRuleParam serialNoRuleParam) {
        SerialNoRuleDO serialNoRuleDO = BeanUtil.convertBean(serialNoRuleParam, SerialNoRuleDO.class);
        serialNoRuleDO.setModifyTime(LocalDateTime.now());
        return serialNoRuleMapper.updateById(serialNoRuleDO) > 0;
    }

    @Override
    public SerialNoRuleDTO queryById(Long id) {
        SerialNoRuleDO serialNoRuleDO = serialNoRuleMapper.selectById(id);
        return BeanUtil.convertBean(serialNoRuleDO, SerialNoRuleDTO.class);
    }

    @Override
    public List<SerialNoRuleDTO> queryByKeyCode(String  keyCode) {
        List<SerialNoRuleDO> serialNoRuleDO = serialNoRuleMapper.selectList(new LambdaQueryWrapper<>(SerialNoRuleDO.class)
                .eq(SerialNoRuleDO::getKeyCode, keyCode)
                .orderByAsc(SerialNoRuleDO::getOrderNo)
        );
        List<SerialNoRuleDTO> serialNoRuleDTOS = JsonUtils.jsonToList(serialNoRuleDO, SerialNoRuleDTO.class);
        return serialNoRuleDTOS;
    }

    @Override
    public Boolean del(Long id) {
        return serialNoRuleMapper.deleteById(id) > 0;
    }

    @Override
    public Boolean delByKeyCode(List<Long> ids) {
        return serialNoRuleMapper.deleteBatchIds(ids) > 0;
    }
    @Override
    public SerialNumberDTO generateSerialNo(String scenCode)  {
        Long shopId= getShopId();
        return getBean().generateSerialNo(scenCode, shopId);
    }
    @Override
    public SerialNumberDTO generateSerialNo(String scenCode, Long shopId)  {
        Assert.notNull(scenCode,"场景键不能为空");
        String keyCode = scenCode + ":" + shopId;
        StringBuilder ruleSerialNumbers = new StringBuilder();
        List<SerialNoRuleDTO> serialNoRuleDTOS = queryByKeyCode(keyCode);
        LogUtils.info(LogClassifyEnum.TRACE_LOG,"入参:{},serialNoRuleDTOS:{}", keyCode, serialNoRuleDTOS);
        if (Collections3.isEmpty(serialNoRuleDTOS)) throw new BusinessException("kecode 不能为空");
        serialNoRuleDTOS.stream().sorted(Comparator.comparing(SerialNoRuleDTO::getOrderNo)).forEach(serialNoRuleDTO -> {
            int orderNo = serialNoRuleDTO.getOrderNo();
            int dataType = serialNoRuleDTO.getDataType();
            String initalData = serialNoRuleDTO.getInitialData();
            String formula = serialNoRuleDTO.getFormula();
            if(dataType == Types.VARCHAR){
                    ruleSerialNumbers.append(formula);
            }else if(dataType == Types.DATE){
                    DateTimeFormatter dateTimeFormatter = SimpleDateFormatter.formatter(formula);
                    if(dateTimeFormatter == null) dateTimeFormatter = SimpleDateFormatter.FORMATTER_DAY;
                    String dateStr = (dateTimeFormatter != null) ? dateTimeFormatter.format(LocalDateTime.now()) : "";
                    ruleSerialNumbers.append(dateStr);
            }else if(dataType == Types.NUMERIC){
                    if(!StringUtils.isNumeric(formula.trim())) throw new BusinessException("数字位数必须是数字");
                    if(StringUtils.isEmpty(initalData)) initalData = "0";
                    if(!StringUtils.isNumeric(initalData.trim())) throw new BusinessException("初始值必须是数字");
                    int digit = Integer.parseInt(formula.trim());
                    long initdata = Long.parseLong(initalData);
                    String serailNumeric = redisIdTemplate.next(keyCode, digit, initdata);
                    ruleSerialNumbers.append(serailNumeric);
                }
        });
        SerialNumberDTO serialNumberDTO = new SerialNumberDTO();
        serialNumberDTO.setRuleSerialNumbers(ruleSerialNumbers.toString());
        LogUtils.info("=========生成序列号:{}=========",JsonUtils.toJsonStr(serialNumberDTO));
        return serialNumberDTO;
    }
    /*
     * 合同规则code
     */
    @Override
    public Boolean saveContractSerialNoRule(List<ContractSerialNoRuleParam> params) {
        Long userId = UserUtils.getUserId();
        Long shopId= getShopId();
        //位数最大为19位
        LogUtils.info("=========params:{}=========",JsonUtils.toJsonStr(params));
        String keyCode = SerialNumberTypeEnum.CONTRACT_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //DTO 入库参数
        List<SerialNoRuleDO> serialNoRules = new ArrayList<>();
        params.forEach(param ->{
            SerialNoRuleDO serialNoRule = new SerialNoRuleDO();
            if (param.getDataType() == 2) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().equalsIgnoreCase("YYYYMMDD") ? "yyyyMMdd" : "yyyyMMddHHmmss");
                serialNoRule.setDataType(Types.DATE);
            }if (param.getDataType() == 1) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula());
                serialNoRule.setDataType(Types.VARCHAR);
            }if (param.getDataType() == 3) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().length()+"");
                serialNoRule.setInitialData(param.getFormula().substring(param.getFormula().length() - 1));
                serialNoRule.setDataType(Types.NUMERIC);
            }
            serialNoRule.setCreateTime(LocalDateTime.now());
            serialNoRule.setCreateBy(userId);
            serialNoRule.setModifyTime(LocalDateTime.now());
            serialNoRule.setModifyBy(userId);
            serialNoRules.add(serialNoRule);
        });
        LogUtils.info("=========serialNoRules:{}=========",JsonUtils.toJsonStr(serialNoRules));
        //删除
        serialNoRuleMapper.deleteSerialNoRuleByCode(scenCode);

        serialNoRuleMapper.insertBatchSomeColumn(serialNoRules);
        return Boolean.TRUE;
    }

    @Override
    public List<ContractSerialNoRuleDTO> queryContractSerialNoRule() {
        Long shopId= getShopId();
        String keyCode = SerialNumberTypeEnum.CONTRACT_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //合同code配置列表
        List<SerialNoRuleDO> serialNoRuleDOS = serialNoRuleMapper.selectList(new LambdaQueryWrapper<>(SerialNoRuleDO.class)
                .eq(SerialNoRuleDO::getKeyCode, scenCode)
                .orderByAsc(SerialNoRuleDO::getOrderNo)
        );
        if (Collections3.isEmpty(serialNoRuleDOS)) {
            return new ArrayList<ContractSerialNoRuleDTO>() ;
        }
        LogUtils.info("=========serialNoRuleDOS:{}=========",JsonUtils.toJsonStr(serialNoRuleDOS));
        List<ContractSerialNoRuleDTO> result = serialNoRuleDOS.stream().map(s -> {
            ContractSerialNoRuleDTO codeSelVO = new ContractSerialNoRuleDTO();
            if (s.getDataType() == Types.DATE) {
                String formula = s.getFormula().replace("-", "");
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(2);
                codeSelVO.setDataTypeDesc("年月日");
            }
            if (s.getDataType() == Types.VARCHAR) {
                codeSelVO.setFormula(s.getFormula());
                codeSelVO.setDataLength(s.getFormula().length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(1);
                codeSelVO.setDataTypeDesc("字符");
            }
            if (s.getDataType() == Types.NUMERIC) {
                String formula = strAppend(s.getFormula(), s.getInitialData());
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(3);
                codeSelVO.setDataTypeDesc("随机数");
            }
            return codeSelVO;
        }).collect(Collectors.toList());
        LogUtils.info("=========result:{}=========",JsonUtils.toJsonStr(result));
        return result;
    }
    /*
     * 订单规则code
     */
    @Override
    public Boolean saveOrderSerialNoRule(List<OrderSerialNoRuleParam> params) {
        Long userId = UserUtils.getUserId();
        Long shopId= getShopId();
        //位数最大为19位
        LogUtils.info("=========params:{}=========",JsonUtils.toJsonStr(params));
        String keyCode = SerialNumberTypeEnum.ORDER_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //DTO 入库参数
        List<SerialNoRuleDO> serialNoRules = new ArrayList<>();
        params.forEach(param ->{
            SerialNoRuleDO serialNoRule = new SerialNoRuleDO();
            if (param.getDataType() == 2) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().equalsIgnoreCase("YYYYMMDD") ? "yyyyMMdd" : "yyyyMMddHHmmss");
                serialNoRule.setDataType(Types.DATE);
            }if (param.getDataType() == 1) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula());
                serialNoRule.setDataType(Types.VARCHAR);
            }if (param.getDataType() == 3) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().length()+"");
                serialNoRule.setInitialData(param.getFormula().substring(param.getFormula().length() - 1));
                serialNoRule.setDataType(Types.NUMERIC);
            }
            serialNoRule.setCreateTime(LocalDateTime.now());
            serialNoRule.setCreateBy(userId);
            serialNoRule.setModifyTime(LocalDateTime.now());
            serialNoRule.setModifyBy(userId);
            serialNoRules.add(serialNoRule);
        });
        LogUtils.info("=========serialNoRules:{}=========",JsonUtils.toJsonStr(serialNoRules));
        //删除
        serialNoRuleMapper.deleteSerialNoRuleByCode(scenCode);

        serialNoRuleMapper.insertBatchSomeColumn(serialNoRules);
        return Boolean.TRUE;
    }

    @Override
    public List<OrderSerialNoRuleDTO> queryOrderSerialNoRule() {
        Long shopId= getShopId();
        String keyCode = SerialNumberTypeEnum.ORDER_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //合同code配置列表
        List<SerialNoRuleDO> serialNoRuleDOS = serialNoRuleMapper.selectList(new LambdaQueryWrapper<>(SerialNoRuleDO.class)
                .eq(SerialNoRuleDO::getKeyCode, scenCode)
                .orderByAsc(SerialNoRuleDO::getOrderNo)
        );
        if (Collections3.isEmpty(serialNoRuleDOS)) {
            return new ArrayList<OrderSerialNoRuleDTO>() ;
        }
        LogUtils.info("=========serialNoRuleDOS:{}=========",JsonUtils.toJsonStr(serialNoRuleDOS));
        List<OrderSerialNoRuleDTO> result = serialNoRuleDOS.stream().map(s -> {
            OrderSerialNoRuleDTO codeSelVO = new OrderSerialNoRuleDTO();
            if (s.getDataType() == Types.DATE) {
                String formula = s.getFormula().replace("-", "");
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(2);
                codeSelVO.setDataTypeDesc("年月日");
            }
            if (s.getDataType() == Types.VARCHAR) {
                codeSelVO.setFormula(s.getFormula());
                codeSelVO.setDataLength(s.getFormula().length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(1);
                codeSelVO.setDataTypeDesc("字符");
            }
            if (s.getDataType() == Types.NUMERIC) {
                String formula = strAppend(s.getFormula(), s.getInitialData());
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(3);
                codeSelVO.setDataTypeDesc("随机数");
            }
            return codeSelVO;
        }).collect(Collectors.toList());
        LogUtils.info("=========result:{}=========",JsonUtils.toJsonStr(result));
        return result;
    }
    /*
     * 会员卡号规则code
     */
    @Override
    public Boolean saveMemberCardNoRule(List<MemberCardNoRuleParam> params) {
        Long userId = UserUtils.getUserId();
        Long shopId= getShopId();
        //位数最大为19位
        LogUtils.info("=========params:{}=========",JsonUtils.toJsonStr(params));
        String keyCode = SerialNumberTypeEnum.MEMBER_CARD_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //DTO 入库参数
        List<SerialNoRuleDO> serialNoRules = new ArrayList<>();
        params.forEach(param ->{
            SerialNoRuleDO serialNoRule = new SerialNoRuleDO();
            if (param.getDataType() == 2) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().equalsIgnoreCase("YYYYMMDD") ? "yyyyMMdd" : "yyyyMMddHHmmss");
                serialNoRule.setDataType(Types.DATE);
            }if (param.getDataType() == 1) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula());
                serialNoRule.setDataType(Types.VARCHAR);
            }if (param.getDataType() == 3) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().length()+"");
                serialNoRule.setInitialData(param.getFormula().substring(param.getFormula().length() - 1));
                serialNoRule.setDataType(Types.NUMERIC);
            }
            serialNoRule.setCreateTime(LocalDateTime.now());
            serialNoRule.setCreateBy(userId);
            serialNoRule.setModifyTime(LocalDateTime.now());
            serialNoRule.setModifyBy(userId);
            serialNoRules.add(serialNoRule);
        });
        LogUtils.info("=========serialNoRules:{}=========",JsonUtils.toJsonStr(serialNoRules));
        //删除
        serialNoRuleMapper.deleteSerialNoRuleByCode(scenCode);

        serialNoRuleMapper.insertBatchSomeColumn(serialNoRules);
        return Boolean.TRUE;
    }

    @Override
    public List<MemberCardNoRuleDTO> queryMemberCardNoRule() {
        Long shopId= getShopId();
        String keyCode = SerialNumberTypeEnum.MEMBER_CARD_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //合同code配置列表
        List<SerialNoRuleDO> serialNoRuleDOS = serialNoRuleMapper.selectList(new LambdaQueryWrapper<>(SerialNoRuleDO.class)
                .eq(SerialNoRuleDO::getKeyCode, scenCode)
                .orderByAsc(SerialNoRuleDO::getOrderNo)
        );
        if (Collections3.isEmpty(serialNoRuleDOS)) {
            return new ArrayList<MemberCardNoRuleDTO>() ;
        }
        LogUtils.info("=========serialNoRuleDOS:{}=========",JsonUtils.toJsonStr(serialNoRuleDOS));
        List<MemberCardNoRuleDTO> result = serialNoRuleDOS.stream().map(s -> {
            MemberCardNoRuleDTO codeSelVO = new MemberCardNoRuleDTO();
            if (s.getDataType() == Types.DATE) {
                String formula = s.getFormula().replace("-", "");
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(2);
                codeSelVO.setDataTypeDesc("年月日");
            }
            if (s.getDataType() == Types.VARCHAR) {
                codeSelVO.setFormula(s.getFormula());
                codeSelVO.setDataLength(s.getFormula().length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(1);
                codeSelVO.setDataTypeDesc("字符");
            }
            if (s.getDataType() == Types.NUMERIC) {
                String formula = strAppend(s.getFormula(), s.getInitialData());
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(3);
                codeSelVO.setDataTypeDesc("随机数");
            }
            return codeSelVO;
        }).collect(Collectors.toList());
        LogUtils.info("=========result:{}=========",JsonUtils.toJsonStr(result));
        return result;
    }
    /*
     * 库存入库单号规则code
     */
    @Override
    public Boolean saveInstockSerialNoRule(List<InstockSerialNoRuleParam> params) {
        Long userId = UserUtils.getUserId();
        Long shopId= getShopId();
        String keyCode = SerialNumberTypeEnum.INVENTORY_INSTOCK_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //位数最大为19位
        LogUtils.info("=========params:{}=========",JsonUtils.toJsonStr(params));
        //DTO 入库参数
        List<SerialNoRuleDO> serialNoRules = new ArrayList<>();
        params.forEach(param ->{
            SerialNoRuleDO serialNoRule = new SerialNoRuleDO();
            if (param.getDataType() == 2) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().equalsIgnoreCase("YYYYMMDD") ? "yyyyMMdd" : "yyyyMMddHHmmss");
                serialNoRule.setDataType(Types.DATE);
            }if (param.getDataType() == 1) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula());
                serialNoRule.setDataType(Types.VARCHAR);
            }if (param.getDataType() == 3) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().length()+"");
                serialNoRule.setInitialData(param.getFormula().substring(param.getFormula().length() - 1));
                serialNoRule.setDataType(Types.NUMERIC);
            }
            serialNoRule.setCreateTime(LocalDateTime.now());
            serialNoRule.setCreateBy(userId);
            serialNoRule.setModifyTime(LocalDateTime.now());
            serialNoRule.setModifyBy(userId);
            serialNoRules.add(serialNoRule);
        });
        LogUtils.info("=========serialNoRules:{}=========",JsonUtils.toJsonStr(serialNoRules));
        //删除
        serialNoRuleMapper.deleteSerialNoRuleByCode(scenCode);

        serialNoRuleMapper.insertBatchSomeColumn(serialNoRules);
        return Boolean.TRUE;
    }

    @Override
    public List<InstockSerialNoRuleDTO> queryInstockSerialNoRule() {
        Long shopId= getShopId();
        String keyCode = SerialNumberTypeEnum.INVENTORY_INSTOCK_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //合同code配置列表
        List<SerialNoRuleDO> serialNoRuleDOS = serialNoRuleMapper.selectList(new LambdaQueryWrapper<>(SerialNoRuleDO.class)
                .eq(SerialNoRuleDO::getKeyCode, scenCode)
                .orderByAsc(SerialNoRuleDO::getOrderNo)
        );
        if (Collections3.isEmpty(serialNoRuleDOS)) {
            return new ArrayList<InstockSerialNoRuleDTO>() ;
        }
        LogUtils.info("=========serialNoRuleDOS:{}=========",JsonUtils.toJsonStr(serialNoRuleDOS));
        List<InstockSerialNoRuleDTO> result = serialNoRuleDOS.stream().map(s -> {
            InstockSerialNoRuleDTO codeSelVO = new InstockSerialNoRuleDTO();
            if (s.getDataType() == Types.DATE) {
                String formula = s.getFormula().replace("-", "");
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(2);
                codeSelVO.setDataTypeDesc("年月日");
            }
            if (s.getDataType() == Types.VARCHAR) {
                codeSelVO.setFormula(s.getFormula());
                codeSelVO.setDataLength(s.getFormula().length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(1);
                codeSelVO.setDataTypeDesc("字符");
            }
            if (s.getDataType() == Types.NUMERIC) {
                String formula = strAppend(s.getFormula(), s.getInitialData());
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(3);
                codeSelVO.setDataTypeDesc("随机数");
            }
            return codeSelVO;
        }).collect(Collectors.toList());
        LogUtils.info("=========result:{}=========",JsonUtils.toJsonStr(result));
        return result;
    }
    /*
     * 库存出库单号规则code
     */
    @Override
    public Boolean saveOutstockSerialNoRule(List<OutstockSerialNoRuleParam> params) {
        Long userId = UserUtils.getUserId();
        Long shopId= getShopId();
        String keyCode = SerialNumberTypeEnum.INVENTORY_OUTSTOCK_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //位数最大为19位
        LogUtils.info("=========params:{}=========",JsonUtils.toJsonStr(params));
        //DTO 入库参数
        List<SerialNoRuleDO> serialNoRules = new ArrayList<>();
        params.forEach(param ->{
            SerialNoRuleDO serialNoRule = new SerialNoRuleDO();
            if (param.getDataType() == 2) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().equalsIgnoreCase("YYYYMMDD") ? "yyyyMMdd" : "yyyyMMddHHmmss");
                serialNoRule.setDataType(Types.DATE);
            }if (param.getDataType() == 1) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula());
                serialNoRule.setDataType(Types.VARCHAR);
            }if (param.getDataType() == 3) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().length()+"");
                serialNoRule.setInitialData(param.getFormula().substring(param.getFormula().length() - 1));
                serialNoRule.setDataType(Types.NUMERIC);
            }
            serialNoRule.setCreateTime(LocalDateTime.now());
            serialNoRule.setCreateBy(userId);
            serialNoRule.setModifyTime(LocalDateTime.now());
            serialNoRule.setModifyBy(userId);
            serialNoRules.add(serialNoRule);
        });
        LogUtils.info("=========serialNoRules:{}=========",JsonUtils.toJsonStr(serialNoRules));
        //删除
        serialNoRuleMapper.deleteSerialNoRuleByCode(scenCode);

        serialNoRuleMapper.insertBatchSomeColumn(serialNoRules);
        return Boolean.TRUE;
    }

    @Override
    public List<OutstockSerialNoRuleDTO> queryOutstockSerialNoRule() {

        Long shopId= getShopId();
        String keyCode = SerialNumberTypeEnum.INVENTORY_OUTSTOCK_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //合同code配置列表
        List<SerialNoRuleDO> serialNoRuleDOS = serialNoRuleMapper.selectList(new LambdaQueryWrapper<>(SerialNoRuleDO.class)
                .eq(SerialNoRuleDO::getKeyCode, scenCode)
                .orderByAsc(SerialNoRuleDO::getOrderNo)
        );
        if (Collections3.isEmpty(serialNoRuleDOS)) {
            return new ArrayList<OutstockSerialNoRuleDTO>() ;
        }
        LogUtils.info("=========serialNoRuleDOS:{}=========",JsonUtils.toJsonStr(serialNoRuleDOS));
        List<OutstockSerialNoRuleDTO> result = serialNoRuleDOS.stream().map(s -> {
            OutstockSerialNoRuleDTO codeSelVO = new OutstockSerialNoRuleDTO();
            if (s.getDataType() == Types.DATE) {
                String formula = s.getFormula().replace("-", "");
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(2);
                codeSelVO.setDataTypeDesc("年月日");
            }
            if (s.getDataType() == Types.VARCHAR) {
                codeSelVO.setFormula(s.getFormula());
                codeSelVO.setDataLength(s.getFormula().length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(1);
                codeSelVO.setDataTypeDesc("字符");
            }
            if (s.getDataType() == Types.NUMERIC) {
                String formula = strAppend(s.getFormula(), s.getInitialData());
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(3);
                codeSelVO.setDataTypeDesc("随机数");
            }
            return codeSelVO;
        }).collect(Collectors.toList());
        LogUtils.info("=========result:{}=========",JsonUtils.toJsonStr(result));
        return result;
    }
    /*
     * 库存盘点单号规则code
     */
    @Override
    public Boolean saveInvCheckSerialNoRule(List<InvCheckSerialNoRuleParam> params) {
        Long userId = UserUtils.getUserId();
        Long shopId= getShopId();
        String keyCode = SerialNumberTypeEnum.INVENTORY_CHECK_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //位数最大为19位
        LogUtils.info("=========params:{}=========",JsonUtils.toJsonStr(params));
        //DTO 入库参数
        List<SerialNoRuleDO> serialNoRules = new ArrayList<>();
        params.forEach(param ->{
            SerialNoRuleDO serialNoRule = new SerialNoRuleDO();
            if (param.getDataType() == 2) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().equalsIgnoreCase("YYYYMMDD") ? "yyyyMMdd" : "yyyyMMddHHmmss");
                serialNoRule.setDataType(Types.DATE);
            }if (param.getDataType() == 1) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula());
                serialNoRule.setDataType(Types.VARCHAR);
            }if (param.getDataType() == 3) {
                serialNoRule.setKeyCode(scenCode);
                serialNoRule.setOrderNo(param.getOrderNo());
                serialNoRule.setFormula(param.getFormula().length()+"");
                serialNoRule.setInitialData(param.getFormula().substring(param.getFormula().length() - 1));
                serialNoRule.setDataType(Types.NUMERIC);
            }
            serialNoRule.setCreateTime(LocalDateTime.now());
            serialNoRule.setCreateBy(userId);
            serialNoRule.setModifyTime(LocalDateTime.now());
            serialNoRule.setModifyBy(userId);
            serialNoRules.add(serialNoRule);
        });
        LogUtils.info("=========serialNoRules:{}=========",JsonUtils.toJsonStr(serialNoRules));
        //删除
        serialNoRuleMapper.deleteSerialNoRuleByCode(scenCode);

        serialNoRuleMapper.insertBatchSomeColumn(serialNoRules);
        return Boolean.TRUE;
    }

    @Override
    public List<InvCheckSerialNoRuleDTO> queryInvCheckSerialNoRule() {
        Long shopId= getShopId();
        String keyCode = SerialNumberTypeEnum.INVENTORY_CHECK_NO.getKeyCode();
        String scenCode = keyCode + ":" + shopId;
        //合同code配置列表
        List<SerialNoRuleDO> serialNoRuleDOS = serialNoRuleMapper.selectList(new LambdaQueryWrapper<>(SerialNoRuleDO.class)
                .eq(SerialNoRuleDO::getKeyCode, scenCode)
                .orderByAsc(SerialNoRuleDO::getOrderNo)
        );
        if (Collections3.isEmpty(serialNoRuleDOS)) {
            return new ArrayList<InvCheckSerialNoRuleDTO>() ;
        }
        LogUtils.info("=========serialNoRuleDOS:{}=========",JsonUtils.toJsonStr(serialNoRuleDOS));
        List<InvCheckSerialNoRuleDTO> result = serialNoRuleDOS.stream().map(s -> {
            InvCheckSerialNoRuleDTO codeSelVO = new InvCheckSerialNoRuleDTO();
            if (s.getDataType() == Types.DATE) {
                String formula = s.getFormula().replace("-", "");
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(2);
                codeSelVO.setDataTypeDesc("年月日");
            }
            if (s.getDataType() == Types.VARCHAR) {
                codeSelVO.setFormula(s.getFormula());
                codeSelVO.setDataLength(s.getFormula().length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(1);
                codeSelVO.setDataTypeDesc("字符");
            }
            if (s.getDataType() == Types.NUMERIC) {
                String formula = strAppend(s.getFormula(), s.getInitialData());
                codeSelVO.setFormula(formula);
                codeSelVO.setDataLength(formula.length());
                codeSelVO.setOrderNo(s.getOrderNo());
                codeSelVO.setDataType(3);
                codeSelVO.setDataTypeDesc("随机数");
            }
            return codeSelVO;
        }).collect(Collectors.toList());
        LogUtils.info("=========result:{}=========",JsonUtils.toJsonStr(result));
        return result;
    }

    @Override
    public SerialNumberDTO generateSerialNo(List<NoRuleDTO> ruleDTOS , String scenCode) throws ServiceException {
        if (Collections3.isEmpty(ruleDTOS) || StringUtils.isEmpty(scenCode)){
            return null;
        }
        SerialNumberDTO serialNumberDTO = new SerialNumberDTO();
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");

        ruleDTOS = ruleDTOS.stream().sorted(Comparator.comparing(NoRuleDTO::getSort)).collect(Collectors.toList());
        String number = "";
        for (NoRuleDTO ruleDTO : ruleDTOS){

            if (NoRuleEnum.NUM_RANDOM.getCode().equals(ruleDTO.getRuleItem())){
                String randomNumber = serialNumberService.generateNumber(scenCode,ruleDTO.getLength());
                number += randomNumber;
            }
            if (NoRuleEnum.NYR.getCode().equals(ruleDTO.getRuleItem())){
                number += df.format(new Date());
            }
            if (NoRuleEnum.STR.getCode().equals(ruleDTO.getRuleItem()) && ruleDTO.getRuleValue() != null){
                number += ruleDTO.getRuleValue();
            }
        }
        serialNumberDTO.setRuleSerialNumbers(number);
        return serialNumberDTO;
    }

    /**
     * 指定位数拼接"0"
     * @param digit 指定位数
     * @param initdata 初始值
     * @return
     */
    private String strAppend (String digit, String initdata) {
        String re = "";
        for (int i = 0; i < Integer.parseInt(digit.trim()); i++) {
            re += "0";
        }
        return re + initdata;
    }

    private Long getShopId(){
        Long shopId= 0L;
        try{
            shopId = UserUtils.getShopId();
        }catch(Exception ex){
            shopId = 0L;
        }
        return shopId;
    }

    private SerialNoRuleGenerateServiceImpl getBean() {
        return SpringBeanUtil.getBean(this.getClass());
    }

}
